package com.me.study.JVM;

import com.me.study.javaCore.enumm.ColorEnum;

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;

/**
 * 软引用测试：第一次 Full GC 后，如果内存还不够，则进行第二次 Full GC 回收 SoftReference对象，如果还是不够则 OutOfMemoryError
 * 运行参数 -Xmx20m -XX:+PrintGC
 *
 * @author ME
 * @date 2021/1/18
 */
public class SoftReferenceTest {

    private static SoftReference<Map<String, String>> cacheMap;

    static {
        Map<String, String> code2nameMap = new HashMap<>();
        for (ColorEnum type: ColorEnum.values()) {
            code2nameMap.put(type.getCode(), type.getDesc());
        }
        cacheMap = new SoftReference<>(code2nameMap);
    }

    /**
     * 运行参数 -Xmx20m -XX:+PrintGC
     */
    public static void main(String[] args) throws InterruptedException {
        // 100M的缓存数据
        byte[] cacheData = new byte[10 * 1024 * 1024];
        // 将缓存数据用软引用持有
        SoftReference<byte[]> cacheRef = new SoftReference<>(cacheData);

        // 将缓存数据的强引用去除
        cacheData = null;
        System.out.println("========================= 第一次GC前，强引用已删除：" + cacheData + " =========================");
        System.out.println("cacheRef：" + cacheRef.get());
        System.out.println("cacheMap：" + cacheMap.get());

        // 进行一次GC后查看对象的回收情况
        System.out.println("\n========================= 第一次GC后，强引用已删除：" + cacheData + " =========================");
        System.gc();
        // 等待GC
        Thread.sleep(500);
        System.out.println("cacheRef：" + cacheRef.get());
        System.out.println("cacheMap：" + cacheMap.get());

        // 再分配一个120M的对象，看看缓存对象的回收情况
        System.out.println("\n========================= 分配对象即将 OutOfMemoryError 时：" + cacheData + " =========================");
        byte[] newData = new byte[12 * 1024 * 1024];
        System.out.println("cacheRef：" + cacheRef.get());
        System.out.println("cacheMap：" + cacheMap.get());
    }

}
